<template>
  <div class="u-form">
    <el-form
      ref="uForm"
      :model="form"
      :rules="rules"
      :label-width="labelWidth||'6em'"
      :show-message="mode === 'form'"
      @submit.prevent
    >
      <template v-if="mode === 'form'">
        <el-row :gutter="10">
          <template v-for="item in formArray">
            <el-col v-if="item.slot" :span="item.col||24">
              <el-form-item :label="item.label" :rules="item.rule||[]" :prop="item.key">
                <slot :name="item.slot" :row="item"/>
              </el-form-item>
            </el-col>
            <el-col v-else :span="item.col||24">
              <el-form-item :label="item.label" :rules="item.rule||[]" :prop="item.key">
                <div :class="{'item-wrap': mode === 'form'}">
                  <template v-if="item.type === 'input'">
                    <el-input
                      v-model="form[item.key]"
                      :placeholder="item.placeholder||'请输入'+item.label"
                      style="width: 100%"
                      v-bind="item.attr"
                      clearable
                      @focus="inputClick(item)"/>
                  </template>
                  <template v-if="item.type === 'textarea'">
                    <el-input
                      v-model="form[item.key]"
                      :placeholder="item.placeholder||'请输入'+item.label"
                      style="width: 100%"
                      type="textarea"
                      :rows="item.rows"
                      v-bind="item.attr"
                      clearable
                      @focus="inputClick(item)"
                    />
                  </template>
                  <template v-if="item.type === 'click'">
                    <div @click="$emit('selectLinkTable',item)">
                      <el-input
                        v-model="form[item.key]"
                        :placeholder="item.placeholder||'请选择'+item.label"
                        style="width: 100%"
                        v-bind="item.attr"
                        clearable
                      />
                    </div>
                  </template>
                  <template v-else-if="item.type === 'number'">
                    <el-input-number
                      v-model="form[item.key]"
                      :min="item.min || 0"
                      style="width: 100%"
                      :max="item.max" v-bind="item.attr"
                    />
                  </template>
                  <template v-else-if="item.type === 'select'">
                    <el-select
                      v-model="form[item.key]"
                      style="width: 100%"
                      :disabled="item.disabled || false"
                      :placeholder="item.placeholder|| '请选择'+item.label"
                      v-bind="{multiple: false,clearable: true,filterable: true, ...item.attr}"
                      @change="selectChange(item, $event)">
                      <template v-for="itm in item.options">
                        <el-option
                          :label="itm[(item.props||{}).label]||itm.label"
                          :value="itm[(item.props||{}).value]||itm.value"
                          :key="itm[(item.props||{}).value]||itm.value"
                        />
                      </template>
                    </el-select>
                  </template>
                  <template v-else-if="item.type === 'cascader'">
                    <el-cascader
                      :key="showCascader"
                      style="width: 100%"
                      @change="selectCascader(item, $event)"
                      :options="item.options" v-model="form[item.key]"
                      :placeholder="item.placeholder|| '请选择'+item.label"
                      v-bind="{
                      disabled:false,
                      clearable: true,
                      filterable: true,
                      separator: '/',
                      ...item.attr
                    }"
                      :props="item.props||{}"
                    />
                  </template>
                  <template v-else-if="item.type === 'date'">
                    <template v-if="item.inputType === 'range'">
                      <el-date-picker
                        v-model="form[item.key]"
                        type="daterange"
                        style="width: 100%"
                        :value-format="item.format||'yyyy-MM-dd HH:mm:ss'"
                        :placeholder="item.placeholder||'请选择'+item.label"
                        v-bind="item.attr"
                        start-placeholder="开始日期"
                        end-placeholder="结束日期"
                        @change="timeRangeChange(item,$event)"
                      />
                    </template>
                    <template v-else>
                      <el-date-picker
                        v-model="form[item.key]"
                        type="date"
                        style="width: 100%"
                        :value-format="item.format||'yyyy-MM-dd HH:mm:ss'"
                        :placeholder="item.placeholder||'请选择'+item.label"
                        v-bind="item.attr"
                        :disabled="item.disabled || false"
                      />
                    </template>
                  </template>
                  <template v-else-if="item.type === 'datetime'">
                    <template v-if="item.inputType === 'range'">
                      <el-date-picker
                        style="width: 100%"
                        v-model="form[item.key]"
                        type="datetimerange"
                        :value-format="item.format||'yyyy-MM-dd HH:mm:ss'"
                        :placeholder="item.placeholder||'请选择'+item.label"
                        v-bind="item.attr"
                        start-placeholder="开始时间"
                        end-placeholder="结束时间"
                        @change="timeRangeChange(item,$event)"
                      />
                    </template>
                    <template v-else>
                      <el-date-picker
                        v-model="form[item.key]" type="datetime"
                        style="width: 100%"
                        :value-format="item.format||'yyyy-MM-dd HH:mm:ss'"
                        :placeholder="item.placeholder||'请选择'+item.label"
                        v-bind="item.attr"
                      />
                    </template>
                  </template>
                  <template v-else-if="item.type === 'radio'">
                    <el-radio-group v-model="form[item.key]">
                      <template v-for="radio in item.options">
                        <el-radio :label="radio.value">{{ radio.label }}</el-radio>
                      </template>
                    </el-radio-group>
                  </template>
                  <template v-else-if="item.type === 'text'">
                    {{ form[item.key] }}
                  </template>
                  <template v-else-if="item.type === 'timeText'">
                    {{ form[item.key] ? $moment(form[item.key]).format(item.format || 'YYYY-MM-DD HH:mm:ss') : '-' }}
                  </template>
                  <template v-else-if="item.type === 'img'">
                    <div class="img-wrap" v-if="form[item.key]">
                      <template v-for="img in imgSrcList(form[item.key])">
                        <el-image class="image" :src="img" fit="contain"
                                  :preview-src-list="imgSrcList(form[item.key])"/>
                      </template>
                    </div>
                    <span v-else>无</span>
                  </template>
                  <template v-else-if="item.type === 'file'">
                    <template v-for="item in item.fileList">
                      <a :href="$file+item.url" target="_blank" :alt="item.name">{{ item.name }}</a> <br/>
                    </template>
                  </template>
                  <template v-else-if="item.type === 'upload'">
                    <div @click="uploadEvent(item)">
                      <template v-if="item.inputType === 'image'">
                        <el-upload
                          class="el-uploadImg"
                          ref="image"
                          :action="baseUrl+(item.action||'/file/uploadFile')"
                          :multiple="item.multiple"
                          accept="image/*"
                          :limit="item.limit||5"
                          list-type="picture-card"
                          :on-preview="handlePictureCardPreview"
                          :on-success="handlerSuccess"
                          :file-list="item.fileList"
                          :headers="item.headers"
                          :disabled="item.disabled"
                          :before-upload="beforeUpload"
                          :on-exceed="onExceed"
                          v-bind="item.attr"
                          :on-remove="(file)=>handleRemove(file, item)">
                          <i class="el-icon-plus"></i>
                        </el-upload>
                      </template>
                      <template v-else-if="item.inputType === 'file'">
                        <el-upload
                          :action="baseUrl+(item.action||'/file/uploadFile')"
                          ref="file"
                          :multiple="item.multiple"
                          :limit="item.limit||5"
                          :on-preview="handlePictureCardPreview"
                          :on-success="handlerSuccess"
                          :file-list="item.fileList"
                          :headers="item.headers"
                          :disabled="item.disabled"
                          :before-upload="beforeUpload"
                          :on-exceed="onExceed"
                          v-bind="item.attr"
                          :on-remove="(file)=>handleRemove(file, item)">
                          <el-button type="primary" size="mini">添加文件</el-button>
                        </el-upload>
                      </template>
                    </div>
                  </template>
                  <template v-else-if="item.type === 'editor'">
                    <Editor
                      v-model="form[item.key]"
                      :min-height="192"
                    />
                  </template>
                  <div v-if="item.tip" class="tip" style="display: inline-block">
                    {{ item.tip || '' }}
                  </div>
                </div>
              </el-form-item>
            </el-col>
          </template>
          <el-col :span="24">
            <el-form-item align="right">
              <div style="text-align: right; width: 100%">
                <slot name="submitBtn">
                  <el-button @click="$emit('close')">取消</el-button>
                  <el-button type="primary" @click="submit" v-loading="loading">提交</el-button>
                </slot>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
      </template>

      <template v-else>
        <el-row :gutter="10">
          <template v-for="item in renderDetailArray">
            <el-col v-if="item.slot" :span="item.col||24">
              <el-form-item :label="item.label" :rules="item.rule||[]" :prop="item.key">
                <slot :name="item.slot" :row="item"/>
              </el-form-item>
            </el-col>
            <el-col v-else :span="item.col||24">
              <el-form-item :label="item.label" :rules="item.rule||[]" :prop="item.key">
                <div class="detail">
                  <template v-if="item.type === 'text'">{{ form[item.key] }}</template>
                  <template v-else-if="item.type === 'select'">
                    {{
                      getDictLabel(
                        item.options,
                        form[item.key],
                        item.props ? item.props.value : 'value',
                        item.props ? item.props.label : 'label'
                      )
                    }}
                  </template>
                  <template v-else-if="item.type === 'img'">
                    <div class="img-wrap" v-if="form[item.key]">
                      <template v-for="img in imgSrcList(form[item.key])">
                        <el-image
                          class="image"
                          :src="img"
                          fit="contain"
                          :preview-src-list="imgSrcList(form[item.key])"
                        />
                      </template>
                    </div>
                    <span v-else>无</span>
                  </template>
                  <template v-else-if="item.type === 'file'">
                    <template v-for="item in item.fileList">
                      <a :href="$file+item.url" target="_blank" :alt="item.name">{{ item.name }}</a> <br/>
                    </template>
                  </template>
                  <template v-else-if="item.type === 'upload'">
                    <div @click="uploadEvent(item)">
                      <template v-if="item.inputType === 'image'">
                        <el-upload
                          class="el-uploadImg"
                          ref="image"
                          :action="baseUrl+(item.action||'/file/uploadFile')"
                          :multiple="item.multiple"
                          accept="image/*"
                          :limit="item.limit||5"
                          list-type="picture-card"
                          :on-preview="handlePictureCardPreview"
                          :on-success="handlerSuccess"
                          :file-list="item.fileList"
                          :headers="item.headers"
                          :disabled="item.disabled"
                          :before-upload="beforeUpload"
                          :on-exceed="onExceed"
                          v-bind="item.attr"
                          :on-remove="handleRemove">
                          <i class="el-icon-plus"></i>
                        </el-upload>
                      </template>
                      <template v-else-if="item.inputType === 'file'">
                        <el-upload
                          :action="baseUrl+(item.action||'/file/uploadFile')"
                          ref="file"
                          :multiple="item.multiple"
                          :limit="item.limit||5"
                          :on-preview="handlePictureCardPreview"
                          :on-success="handlerSuccess"
                          :file-list="item.fileList"
                          :headers="item.headers"
                          :disabled="item.disabled"
                          :before-upload="beforeUpload"
                          :on-exceed="onExceed"
                          v-bind="item.attr"
                          :on-remove="handleRemove"
                          disabled
                        />
                      </template>
                    </div>
                  </template>
                  <template v-else-if="item.type === 'editor'">
                    <Editor
                      v-model="form[item.key]"
                      :min-height="192"
                      read-only
                    />
                  </template>
                  <template v-else-if="item.type == 'time' && form[item.key]">
                    {{ $moment(form[item.key]).format(item.format || 'YYYY-MM-DD HH:mm:ss') }}
                  </template>
                  <template v-else>{{ form[item.key] }}</template>
                </div>
              </el-form-item>
            </el-col>
          </template>
        </el-row>
      </template>
    </el-form>
  </div>
</template>

<script>
import Editor from "@/components/Editor";
export default {
  name: "uForm",
  components: {
    Editor
  },
  props: {
    formArray: {
      type: Array,
      default: () => []
    },
    detailArray: {
      type: Array,
      default: () => []
    },
    value: {
      type: Object,
      default: () => {
        return {}
      }
    },
    labelWidth: String,
    defaultForm: {
      type: Object,
      default: () => {
        return {}
      }
    },
    mode: { // form or text
      type: String,
      default: 'form'
    }
  },
  data() {
    const rules = {}
    this.formArray.forEach(item => {
      rules[item.key] = item.rule || []
    })
    return {
      form: this.value,
      rules,
      showCascader: 0,
      loading: false,
      checkAll: false,
      isIndeterminate: true,
      baseUrl: process.env.VUE_APP_BASE_API
    }
  },
  computed: {
    renderDetailArray() {
      if (this.mode === 'form') {
        return this.formArray
      } else {
        if (this.detailArray) {
          return this.detailArray
        } else {
          return this.formArray
        }
      }
    }
  },
  created() {

  },
  watch: {
    form: {
      deep: true,
      handler(val) {
        this.$nextTick(() => {
          Array.from(document.getElementsByClassName('el-popper')).forEach(item => {
            if (item.style.top === '0px' && item.style.position === 'fixed') {
              document.body.removeChild(item)
            }
          })
        })
        this.$emit('input', val)
        this.$emit('change', val)
      }
    },
    value: {
      deep: true,
      handler(val) {
        this.form = val
      }
    },
  },

  methods: {
    imgSrcList(value) {
      if (Array.isArray(value)) {
        return value
      } else if (typeof value === 'string') {
        return value.split(',')
      }
      return value
    },
    inputClick(item) {
      if ('emit' in item) {
        this.$emit(item.emit, item)
      }
    },
    // labelKey  字符串  对象
    selectChange(item, val) {
      let cacheStr = []
      this.$emit(item.emit || '', val)
      if (!val.multiple && item.labelKey) {
        const label = item.props ? (item.props.label || 'label') : 'label'
        const value = item.props ? (item.props.value || 'value') : 'value'
        const target = item.options.find(item => item[value] === val)
        if (typeof item.labelKey === 'string') {
          this.form[item.labelKey] = target[label]
        } else {
          Object.keys(item.labelKey).forEach(key => {
            this.form[key] = target[item.labelKey[key]]
          })
        }
      }
    },
    selectCascader(item, val) {
      if (item.emit) {
        this.$emit(item.emit, val)

      }
      if (item.keys) {
        item.keys.forEach((item, index) => {
          this.$set(this.form, item.keys[index], val[index])
        })
      }
      this.showCascader++
    },
    timeRangeChange(item, time) {
      this.form[item.start || 'startDate'] = time ? time[0] : null
      this.form[item.end || 'endDate'] = time ? time[1] : null
    },
    reset() {
      Object.keys(this.form).forEach(key => {
        this.form[key] = this.defaultForm[key] || null
      })
      if (this.$refs.file) {
        this.$refs.file.forEach(item => {
          item.clearFiles()
        })
      }
      if (this.$refs.image) {
        this.$refs.image.forEach(item => {
          item.clearFiles()
        })
      }
      this.$nextTick(()=>{
        this.$refs.uForm.clearValidate();
      })
    },
    submit() {
      this.$refs.uForm.validate(async (val) => {
        if (val) {
          this.loading = true
          this.$emit('submit', () => {
            this.loading = false
            // this.reset()
          })
        }
      })
    },
    uploadEvent(val) {
      console.log(val)
      this.target = val
    },
    onExceed() {
      this.$message.warning('已超出上传数量限制')
    },
    handlePictureCardPreview(file) {
      console.log(file)
      window.open(file.url, '_black')
    },
    beforeUpload(val) {
      console.log(val)
      if (this.target.labelKey || this.target.saveFileName) {
        if (this.target.limit === 1) {
          this.form[this.target.labelKey] = file.name
        } else {
          if (!Array.isArray(this.form[this.target.key])) {
            this.form[this.target.key] = []
          }
          this.form[this.target.key].push({name: file.name, url: '', key: this.target.key})
        }
      }
      this.$emit('beforeUpload',this.target.key, val)
    },
    handlerSuccess(val) {
      console.log(val)
      let value = this.form[this.target.key]
      value = value ? value.split(',') : []
      value.push(val.data)
      value = value.join(',')
      this.form[this.target.key] = value
    },
    handleRemove(file, item) {
      if(item.limit === 1) {
        item.fileList = []
        this.form[item.key] = ''
      }else {
        let value = this.form[file.key] ? this.form[file.key].split(',') : []
        value.forEach((item, index) => {
          if (item === file.src || item === file.response.data) {
            value.splice(index, 1)
          }
        })
        this.form[file.key] = value.join(',')
      }

    },
    handleCheckAllChange(val) {
      this.checkedCities = val ? options : [];
      this.isIndeterminate = false;
    },
  }
}
</script>

<style scoped lang="scss">
.img-wrap {
  display: flex;
  flex-wrap: wrap;

  .image {
    width: 100px;
    height: 100px;
    margin-right: 10px;
    margin-bottom: 10px;
    background: #f5f7fa;
  }
}

.item-wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 40px;

  .tip {
    margin-left: 1em;
  }
}

.foot-btn {
  display: flex;
  align-items: center;
  background: red;
}
</style>
